import queue
from strategy import BuyAndHoldStrategy
from data import HistoricCSVDataHandler

class Backtest(object):
    def __init__(self,strategy_cls):
        self.events = queue.Queue()
        self._data_handler = HistoricCSVDataHandler(self.events,'../csv_data/testdata',['600008','600018'])
        self._portfolio = SimplePortfolio(self._data_handler,self.events)
        self._execution = SimulatedExecutionHandler(self.events)
        self._strategy = strategy_cls(self._data_handler,self.events)
        self._init_event_handlers()
        
    #挂载事件，每个事件类型对应一个处理函数
    def _init_event_handlers(self):
        self._event_handler = {}
        self._event_handler['BAR'] = self._handle_event_bar
        self._event_handler['SIGNAL'] = self._handle_event_signal
        self._event_handler['ORDER'] = self._handle_event_order
        self._event_handler['FILL'] = self._handle_event_fill

    #主系统入口
    def run(self):
        while True:
            #每次loop，都会让data_handler触发新的bar事件，即有一个新bar到达
            #b_continue_backtest是数据管理器的标志，置False则回测停止
            if self._data_handler.b_continue_backtest:
                self._data_handler.update_bars()
            else:
                break
            #可能有多事件，要处理完，如果队列暂时是空的，不处理
            while True:
                #队列为空则消息循环结束
                try:
                    event = self.events.get(False)
                except queue.Empty:
                    break
                else:
                    self._handle_event(event)
           
            # 10-Minute heartbeat
            #time.sleep(10*60)

    def show_results(self):
        self._portfolio.output_summary_stats()

    def _handle_event(self,event):
        handler = self._event_handler.get(event.type,None)
        if handler is None:
            print('type:%s,handler is None'%event.type)
        else:
            handler(event)

    def _handle_event_bar(self,event):
        print('OnBar Event',event.type)
        self._strategy.onbar()
        self._portfolio.update_timeindex()

    #处理策略产生的交易信号
    def _handle_event_signal(self,event):
        print('OnSignal Event', event.type)
        self._portfolio.on_signal(event)

    # 处理ORDER
    def _handle_event_order(self, event):
        print('OnOrder Event', event.type)
        self._execution.execute_order(event)

    # 处理FILL
    def _handle_event_fill(self, event):
        print('OnFill Event', event.type)
        self._portfolio.on_fill(event)
        

if __name__=="__main__":
    backtest=Backtest(BuyAndHoldStrategy)
    backtest.run()